package com.ltkj.baseplatform.util;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.ltkj.common.core.utils.StringUtils;
import com.ltkj.common.core.web.domain.AjaxResult;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.faceid.v20180301.FaceidClient;
import com.tencentcloudapi.faceid.v20180301.models.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Objects;

/**
 * @Author: xupf
 * @Date: 2023/09/19
 * @Description: E政通相关
 */
public class EidUtil {
    private static final Logger log = LoggerFactory.getLogger(EidUtil.class);

    private FaceidClient buildFaceIdClient(String secretId, String secretKey) {
        // 实例化一个认证对象，入参需要传入腾讯云账户 SecretId 和 SecretKey，此处还需注意密钥对的保密
        // 代码泄露可能会导致 SecretId 和 SecretKey 泄露，并威胁账号下所有资源的安全性。以下代码示例仅供参考，建议采用更安全的方式来使用密钥，请参见：https://cloud.tencent.com/document/product/1278/85305
        // 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取
        Credential cred = new Credential(secretId, secretKey);
        // 实例化一个http选项，可选的，没有特殊需求可以跳过
        HttpProfile httpProfile = new HttpProfile();
        httpProfile.setEndpoint("faceid.tencentcloudapi.com");
        // 实例化一个client选项，可选的，没有特殊需求可以跳过
        ClientProfile clientProfile = new ClientProfile();
        clientProfile.setHttpProfile(httpProfile);
        // 实例化要请求产品的client对象,clientProfile是可选的
        return new FaceidClient(cred, "", clientProfile);
    }

    /**
     * 获取EidToken
     * @param idCard
     * @param name
     * @param secretId
     * @param secretKey
     * @param merchantId
     * @return EidToken
     */
    public AjaxResult getEidToken(String idCard, String name,String secretId, String secretKey, String merchantId) {
        FaceidClient client = buildFaceIdClient(secretId, secretKey);
        // 实例化一个请求对象,每个接口都会对应一个request对象
        GetEidTokenRequest req = new GetEidTokenRequest();
        req.setIdCard(idCard);
        req.setName(name);
        req.setMerchantId(merchantId);
        // 小程序模式配置，包括如何传入姓名身份证的配置，以及是否使用意愿核身
        /**
         * 1：传身份证正反面OCR
         * 2：传身份证正面OCR
         * 3：用户手动输入
         * 4：客户后台传入
         */
        GetEidTokenConfig eidTokenConfig = new GetEidTokenConfig();
        eidTokenConfig.setInputType("4");
        req.setConfig(eidTokenConfig);

        try {
            // 返回的resp是一个GetEidTokenResponse的实例，与请求对象对应
            GetEidTokenResponse resp = client.GetEidToken(req);
            log.info("获取EidToken请求参数:{}, {}, {}", req.getIdCard(), req.getName(), req.getMerchantId());
            log.info("获取EidToken返回结果:{}", GetEidTokenResponse.toJsonString(resp));
            return AjaxResult.success("请求成功", resp.getEidToken());
        } catch (Exception e) {
            e.printStackTrace();
            log.error("获取EidToken失败{}", e.getMessage());
            return AjaxResult.error("获取EidToken失败!");
        }
    }

    /**
     * 根据EidToken获取识别结果
     *      建议直接使用getEidResultV2 —— 2023-10-16
     * @param secretId
     * @param secretKey
     * @param eidToken
     * @return
     */
    public AjaxResult getEidResult(String secretId, String secretKey, String eidToken) {
        FaceidClient client = buildFaceIdClient(secretId, secretKey);
        // 实例化一个请求对象,每个接口都会对应一个request对象
        GetEidResultRequest req = new GetEidResultRequest();
        req.setEidToken(eidToken);
        req.setInfoType("1");

        try {
            // 返回的resp是一个GetEidResultResponse的实例，与请求对象对应
            GetEidResultResponse resp = client.GetEidResult(req);
            log.info("获取EidResult请求参数:{}", req.getEidToken());
            log.info("获取EidResult返回结果:{}", GetEidResultResponse.toJsonString(resp));
            return AjaxResult.success("请求成功", resp.getText());
        } catch (Exception e) {
            e.printStackTrace();
            log.error("获取EidResult失败{}", e.getMessage());
            return AjaxResult.error("获取EidResult失败!");
        }
    }

    /**
     * 根据EidToken获取识别结果，并解析返回的报文（checkEidResult）
     * @param secretId
     * @param secretKey
     * @param eidToken
     * @return
     */
    public AjaxResult getEidResultV2(String secretId, String secretKey, String eidToken) {
        FaceidClient client = buildFaceIdClient(secretId, secretKey);
        // 实例化一个请求对象,每个接口都会对应一个request对象
        GetEidResultRequest req = new GetEidResultRequest();
        req.setEidToken(eidToken);
        req.setInfoType("1");

        try {
            // 返回的resp是一个GetEidResultResponse的实例，与请求对象对应
            GetEidResultResponse resp = client.GetEidResult(req);
            log.info("获取EidResult请求参数:{}", req.getEidToken());
            log.info("获取EidResult返回结果:{}", GetEidResultResponse.toJsonString(resp));
            return checkEidResult(AjaxResult.success("请求成功", resp.getText()));
        } catch (Exception e) {
            e.printStackTrace();
            log.error("获取EidResult失败{}", e.getMessage());
            return AjaxResult.error("获取EidResult失败!");
        }
    }

    /**
     * 校验获取识别结果，getEidResult方法可以配合此方法使用
     * @param eidResult eidToken结果
     * @return
     */
    public AjaxResult checkEidResult(AjaxResult eidResult) {
        // E证通接口未报错，继续判断返回报文
        if (eidResult.isSuccess()) {
            Object o = eidResult.get(AjaxResult.DATA_TAG);
            // 判断返回报文中errCode
            if (!Objects.isNull(o) && !StringUtils.equals(o.toString(), "null")) {
                JSONObject entries = JSONUtil.parseObj(o);
                Integer errCode = entries.getInt("ErrCode");
                // 判断认证成功后保存数据库
                if (null != errCode && errCode.equals(0)) {
                    return AjaxResult.success("认证成功");
                } else {
                    return AjaxResult.error("认证失败");
                }
            } else {
                return AjaxResult.error("报文解析失败", o);
            }
        }
        return eidResult;
    }
}
